#ifndef VISUALSERVER_H
#define VISUALSERVER_H

#include <vector>
#include <queue>
#include <stack>

#include "protocol.h"
#include "cameradaemon.h"
#include "transferdaemon.h"
#include "ptzcontrol.h"
#include "targettrack.h"
#include "searchablequeue.h"
#include "timestamp.h"

typedef struct image_block_ref{
    unsigned int timestamp;
    int block;
}image_block_ref_t;

#define VISUAL_SERVER_INTERVAL 40
class VisualServer
{
public:
    VisualServer();
    ~VisualServer();
    bool setCaptureSize(int width, int height);
    bool answerSyncRequest(normal_request_t request, normal_response_t &response);
    bool answerCameraRequest(normal_request_t request, normal_response_t &response);
    bool answerPtzRequest(normal_request_t request, normal_response_t &response);
    bool answerImageRequest(normal_request_t request, normal_response_t &response);
    void imageTransferDaemon();
    void syncHandler(normal_request_t request, struct sockaddr_in addr, socklen_t addr_len);
    void infoHandler(normal_request_t request, struct sockaddr_in addr, socklen_t addr_len);
    void dataHandler(normal_request_t request, struct sockaddr_in addr, socklen_t addr_len);
    void run(int argc, const char** argv);
private:
    void sendImageBlock(unsigned int ts, std::vector<unsigned char>&  data, int block, struct sockaddr_in _addr ,socklen_t _addr_len);
    void packResponse(void *response);
    void sendPtzInfo(int interval = 30);
    void sendCameraInfo(int interval = 30);
    void sendImageInfo(cv::Mat& img, unsigned int ts, int interval = 10);
private:
    CameraDaemon m_camera;
    TransferDaemon m_transfer;
    PtzControl m_ptz;

    //for image transportation
    sem_t m_transfer_mutex;
    sem_t m_transfer_sync;
    SearchableQueue<unsigned int, std::vector<unsigned char> > m_image_data_queue;
    std::queue<image_block_ref_t> m_need_to_tran;
    unsigned int m_cur_image_ts;
    pthread_t m_tran_thread;
    bool m_tran_existing;
    bool m_tran_switch;
    int m_tran_interval;

    //for transportation
    bool m_has_connection;
    sem_t m_transfer_addr_mutex;
    struct sockaddr_in m_tran_addr;
    socklen_t m_tran_addr_len;

};


#endif // VISUALSERVER_H
